<!--
 * @Author: aster lipian1004@163.com
 * @Date: 2025-02-20 17:11:47
 * @FilePath: \aster-flowable-uniapp\src\components\form\render\table-list.vue
 * @Description: 明细表
 * Copyright (c) 2025 by Aster, All Rights Reserved.
-->
<template>
  <view class="collapse" v-show="!_hidden">
    <van-field
      v-model="fieldValue"
      :name="formItem.id"
      :rules="_rules"
      :border="false"
      :required="_required"
      :readonly="_readonly"
      :input-align="FieldInputAlignEnum.RIGHT"
      :error-message-align="FieldInputAlignEnum.RIGHT"
      clearable
    >
      <template #label>
        <span class="field-title">{{ props.formItem?.title }}</span>
      </template>
      <template #input>
        <text />
      </template>
    </van-field>
    <van-collapse v-model="activeNames" ref="collapseRef">
      <view v-if="isNotEmpty(_value)">
        <van-collapse-item
          :title="index"
          :name="index"
          v-for="(valItem, index) in _value"
          :key="index"
        >
          <template #title>
            <view class="collapse__title">
              <text>第 {{ index + 1 }} 项</text>
              <van-icon v-if="!_readonly" name="delete-o" @click="delLine(index)" />
            </view>
          </template>
          <template v-for="(col, i) in _columns" :key="i">
            <form-design-render
              v-model:value="valItem[col.id]"
              :form-data="formData"
              :form-item="col"
              :mode="mode"
              :table-id="formItem.id"
              :table-index="index"
              :show-label="true"
            />
          </template>
        </van-collapse-item>
      </view>
      <view class="collapse__button">
        <van-button
          type="primary"
          :disabled="_readonly"
          icon="plus"
          plain
          hairline
          size="mini"
          @click="addLine"
        >
          添加数据
        </van-button>
      </view>
    </van-collapse>
  </view>
</template>
<script setup lang="ts">
  import { computed, PropType, ref } from 'vue';
  import { generateUUID } from '@/utils/workflow';
  import FormDesignRender from '@/components/form/form-design-render.vue';
  import { FieldInputAlignEnum } from '@/enums/formEnum';
  import { isNotEmpty } from '@/utils/is';
  import { FormPermissionEnum } from '@/enums/workFlowEnum';
  import { evaluateFormula } from '@/utils/workflow';
  import { Modal } from '@/utils/uniapi/prompt';

  const emits = defineEmits(['update:value']);
  const props = defineProps({
    value: {
      type: Array as PropType<WorkForm.FormDataModel[]>,
      default: () => [],
    },
    mode: {
      type: String as PropType<'design' | 'form' | 'search' | 'table' | 'print'>,
      default: 'design',
    },
    formData: {
      type: Object as PropType<WorkForm.FormDataModel>,
      default: {},
    },
    formItem: {
      type: Object as PropType<WorkComponent.ComponentConfig>,
      default: {},
    },
    tableId: {
      type: String,
      default: '',
    },
    tableIndex: {
      type: Number,
      default: 0,
    },
    showLabel: {
      type: Boolean,
      default: true,
    },
  });

  // 占位字段
  const fieldValue = ref('');
  // 当前展开的面板
  const activeNames = ref<number[]>([]);

  /**
   * @description: 添加行
   * @return {*}
   */
  const addLine = () => {
    console.log(JSON.stringify(_value.value));
    // 使用展开语法来创建对象，提高代码简洁性
    const rowData = _columns.value.reduce((acc, cur) => ({ ...acc, [cur.id]: cur.value }), {});
    // 给每一行数据添加id
    rowData[`id`] = generateUUID();
    // 检查当前_value的类型，确保它可以被push操作
    if (_value.value == null || !Array.isArray(_value.value)) {
      _value.value = [rowData];
    } else {
      _value.value.push(rowData);
    }
    activeNames.value.push(_value.value.length - 1);
  };

  /**
   * @description: 删除行
   * @return {*}
   */
  const delLine = (index: number) => {
    Modal({
      title: '提示',
      content: '您确定要删除该行数据吗？',
    }).then((res: any) => {
      if (res.confirm) {
        _value.value.splice(index, 1);
        activeNames.value.splice(index, 1);
      }
    });
  };

  /**
   * @description: 子组件
   * @return {*}
   */
  const _columns = computed({
    get() {
      if (_readonly.value) {
        return props.formItem.props.columns.map((col) => {
          col.props.readonly = true;
          return col;
        });
      } else {
        return props.formItem.props.columns;
      }
    },
    set(val) {
      props.formItem.props.columns = val;
    },
  });

  /**
   * @description: 组件值
   */
  const _value = computed({
    get() {
      return props.value;
    },
    set(val) {
      emits('update:value', val);
    },
  });

  /**
   * @description: 是否必填, true-必填
   */
  const _required = computed(() => {
    return props.formItem.props.required;
  });

  /**
   * @description: 校验规则
   */
  const _rules = computed(() => {
    const isRequired = _required.value;
    if (props.mode != 'form') {
      return [];
    }
    return isRequired ? [{ required: true, message: `请输入${props.formItem.title}` }] : [];
  });

  /**
   * @description: 是否隐藏, true-隐藏
   */
  const _hidden = computed(() => {
    let r = false;
    // 解析隐藏条件公式
    if (props.formItem.props.hidden) {
      let expression = props.formItem.props.hidden;
      r = evaluateFormula(expression, props.formData);
    }
    // 判断流程节点下该控件是否隐藏
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.HIDDEN;
    }
    return r;
  });

  /**
   * @description: 是否只读, true-只读
   */
  const _readonly = computed(() => {
    let r = props.formItem.props.readonly;
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.READONLY;
    }
    return r;
  });

  defineExpose({
    _hidden,
  });
</script>
<style scoped lang="scss">
  .field-title {
    font-weight: bold;
  }
  .collapse {
    &__title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 30rpx;
    }
    &__button {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      padding: 20rpx 30rpx;
      background-color: #fff;
    }
  }
</style>
